import logging
import os
import time
import gc
from PyQt5.QtWidgets import (QWidget, QVBoxLayout, QLabel, QTableWidget, QTableWidgetItem, QHBoxLayout, 
                           QHeaderView, QAbstractItemView, QPushButton, QLineEdit, QFileDialog, QDialog, 
                           QSplitter, QSizePolicy, QGroupBox, QGridLayout, QRadioButton, QMessageBox, 
                           QScrollArea, QTextEdit, QApplication)
from PyQt5.QtCore import Qt, pyqtSignal, QRegExp
from PyQt5.QtGui import QIntValidator, QRegExpValidator
from frame_processor import FrameProcessor
from progress_dialog import ProgressDialog
from file_loader_thread import FileLoaderThread
from multi_format_file_loader_thread import MultiFormatFileLoaderThread
from multi_format_frame_processor import MultiFormatFrameProcessor
from utils import get_resource_path, format_hex_with_space
from logger import logger
from fast_frame_converter import FastFrameConverter
from high_performance_comparer import HighPerformanceComparer, StreamingComparer
from high_performance_detailed_comparer import OptimizedVirtualChannelComparer
from crash_recovery import safe_compare_decorator
from cython_enhanced_comparer import CythonEnhancedComparer
from cython_integration import get_cython_engine
from optimized_comparer_numpy import OptimizedNumpyComparer

# 内存监控
try:
    import psutil
    HAS_PSUTIL = True
except ImportError:
    HAS_PSUTIL = False

class CompareWidget(QWidget):
    compare_signal = pyqtSignal(dict)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.layout = QVBoxLayout()
        # 移除布局的边距，避免空白区域
        self.layout.setContentsMargins(0, 0, 0, 0)
        self.layout.setSpacing(0)
        
        self.logger = logging.getLogger('frame_analyzer')
        schema_file = get_resource_path('frame_schema.xml')
        self.frame_processor = FrameProcessor(schema_file)
        self.current_comparison = None
        self.current_analysis = None
        
        # 分页相关变量
        self.current_page = 1
        self.total_pages = 1
        self.page_size = 100  # 每页显示100条
        self.all_rows_data = []  # 存储所有需要显示的行数据
        self.page_cache = {}  # 缓存已处理的页面数据

        # 创建左侧控制面板
        left_panel = QWidget()
        left_layout = QVBoxLayout()
        left_panel.setLayout(left_layout)
        # 为左侧面板设置弹性尺寸策略
        left_panel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # 添加手动转换区域
        convert_group = QGroupBox("手动转换")
        convert_layout = QGridLayout()

        # 源文件选择
        convert_layout.addWidget(QLabel("源文件:"), 0, 0)
        self.source_file_path = QLineEdit()
        self.source_file_path.setReadOnly(True)
        self.source_file_path.setPlaceholderText("选择需要转换的源文件")
        convert_layout.addWidget(self.source_file_path, 0, 1)
        self.source_file_btn = QPushButton("浏览...")
        self.source_file_btn.clicked.connect(lambda: self._select_convert_file('source'))
        convert_layout.addWidget(self.source_file_btn, 0, 2)

        # 目标文件选择
        convert_layout.addWidget(QLabel("目标文件夹:"), 1, 0)
        self.target_folder_path = QLineEdit()
        self.target_folder_path.setReadOnly(True)
        self.target_folder_path.setPlaceholderText("选择保存转换后文件的文件夹")
        convert_layout.addWidget(self.target_folder_path, 1, 1)
        self.target_folder_btn = QPushButton("浏览...")
        self.target_folder_btn.clicked.connect(lambda: self._select_convert_file('target'))
        convert_layout.addWidget(self.target_folder_btn, 1, 2)
        
        # 添加转换选项
        convert_layout.addWidget(QLabel("转换选项:"), 2, 0)
        convert_options_layout = QHBoxLayout()
        self.convert_1024_radio = QRadioButton("1024字节")
        self.convert_1024_radio.setChecked(True)  # 默认选择
        self.convert_896_radio = QRadioButton("896字节")
        self.convert_custom_radio = QRadioButton("自定义范围")
        convert_options_layout.addWidget(self.convert_1024_radio)
        convert_options_layout.addWidget(self.convert_896_radio)
        convert_options_layout.addWidget(self.convert_custom_radio)
        convert_layout.addLayout(convert_options_layout, 2, 1, 1, 2)
        
        # 添加自定义范围输入框
        self.custom_range_widget = QWidget()
        custom_range_layout = QHBoxLayout(self.custom_range_widget)
        custom_range_layout.setContentsMargins(0, 0, 0, 0)
        custom_range_layout.addWidget(QLabel("起始字节:"))
        self.custom_start_byte = QLineEdit()
        self.custom_start_byte.setValidator(QIntValidator(0, 1091))
        self.custom_start_byte.setPlaceholderText("0-1091")
        custom_range_layout.addWidget(self.custom_start_byte)
        custom_range_layout.addWidget(QLabel("结束字节:"))
        self.custom_end_byte = QLineEdit()
        self.custom_end_byte.setValidator(QIntValidator(0, 1091))
        self.custom_end_byte.setPlaceholderText("0-1091")
        custom_range_layout.addWidget(self.custom_end_byte)
        custom_range_layout.addStretch()
        self.custom_range_widget.setVisible(False)
        convert_layout.addWidget(self.custom_range_widget, 3, 1, 1, 2)

        # 转换按钮
        self.convert_button = QPushButton("开始转换")
        self.convert_button.setEnabled(False)
        self.convert_button.setStyleSheet("""
            QPushButton {
                background-color: #0064c8;
                color: white;
                border: none;
                padding: 8px 16px;
                font-size: 12px;
                font-weight: bold;
                border-radius: 4px;
                min-width: 100px;
            }
            QPushButton:disabled {
                background-color: #cccccc;
            }
            QPushButton:hover:!disabled {
                background-color: #0055a5;
            }
            QPushButton:pressed:!disabled {
                background-color: #00448a;
            }
        """)
        convert_layout.addWidget(self.convert_button, 4, 1, 1, 2)

        convert_group.setLayout(convert_layout)
        left_layout.addWidget(convert_group)

        # 文件选择区域
        file_group = QGroupBox("文件选择")
        file_layout = QGridLayout()

        # 基准文件格式（先于基准文件选择）
        file_layout.addWidget(QLabel("基准文件格式:"), 0, 0)
        file1_format_group = QWidget()
        file1_format_layout = QHBoxLayout(file1_format_group)
        file1_format_layout.setContentsMargins(0, 0, 0, 0)
        self.file1_1092_radio = QRadioButton("1092字节")
        self.file1_1092_radio.setChecked(True)
        self.file1_1024_radio = QRadioButton("1024字节")
        self.file1_896_radio = QRadioButton("896字节")
        file1_format_layout.addWidget(self.file1_1092_radio)
        file1_format_layout.addWidget(self.file1_1024_radio)
        file1_format_layout.addWidget(self.file1_896_radio)
        file_layout.addWidget(file1_format_group, 0, 1, 1, 2)

        # 基准文件选择
        file_layout.addWidget(QLabel("基准文件:"), 1, 0)
        self.file1_path = QLineEdit()
        self.file1_path.setReadOnly(True)
        self.file1_path.setPlaceholderText("选择基准文件")
        self.file1_btn = QPushButton("浏览...")
        self.file1_btn.clicked.connect(lambda: self._select_file(1))
        file_layout.addWidget(self.file1_path, 1, 1)
        file_layout.addWidget(self.file1_btn, 1, 2)

        # 目标文件格式（先于目标文件选择）
        file_layout.addWidget(QLabel("目标文件格式:"), 2, 0)
        file2_format_group = QWidget()
        file2_format_layout = QHBoxLayout(file2_format_group)
        file2_format_layout.setContentsMargins(0, 0, 0, 0)
        self.file2_1092_radio = QRadioButton("1092字节")
        self.file2_1092_radio.setChecked(True)
        self.file2_1024_radio = QRadioButton("1024字节")
        self.file2_896_radio = QRadioButton("896字节")
        file2_format_layout.addWidget(self.file2_1092_radio)
        file2_format_layout.addWidget(self.file2_1024_radio)
        file2_format_layout.addWidget(self.file2_896_radio)
        file_layout.addWidget(file2_format_group, 2, 1, 1, 2)

        # 目标文件选择
        file_layout.addWidget(QLabel("目标文件:"), 3, 0)
        self.file2_path = QLineEdit()
        self.file2_path.setReadOnly(True)
        self.file2_path.setPlaceholderText("选择目标文件")
        self.file2_btn = QPushButton("浏览...")
        self.file2_btn.clicked.connect(lambda: self._select_file(2))
        file_layout.addWidget(self.file2_path, 3, 1)
        file_layout.addWidget(self.file2_btn, 3, 2)

        file_group.setLayout(file_layout)
        left_layout.addWidget(file_group)
        
        # 添加比对范围选项
        compare_range_group = QGroupBox("比对范围")
        compare_range_layout = QVBoxLayout()
        
        self.compare_1024_radio = QRadioButton("比对1024字节 (f896数据区 + f128数据区)")
        self.compare_1024_radio.setChecked(True)  # 默认选中
        self.compare_896_radio = QRadioButton("比对896字节 (仅f896数据区)")
        
        compare_range_layout.addWidget(self.compare_1024_radio)
        compare_range_layout.addWidget(self.compare_896_radio)
        
        compare_range_group.setLayout(compare_range_layout)
        left_layout.addWidget(compare_range_group)

        # 帧计数范围设置区域
        range_group = QGroupBox("虚拟信道帧计数范围设置")
        range_layout = QGridLayout()

        self.start_frame_count = QLineEdit()
        self.start_frame_count.setPlaceholderText("起始虚拟信道帧计数(十六进制,如:03B64F)")
        self.end_frame_count = QLineEdit()
        self.end_frame_count.setPlaceholderText("结束虚拟信道帧计数(十六进制,如:03B650)")

        # 自定义验证器，允许输入十六进制（最多6位）
        # 匹配1-6位十六进制字符
        hex_validator = QRegExpValidator(QRegExp("^[0-9A-Fa-f]{1,6}$"))
        self.start_frame_count.setValidator(hex_validator)
        self.end_frame_count.setValidator(hex_validator)

        range_layout.addWidget(QLabel("起始虚拟信道帧计数:"), 0, 0)
        range_layout.addWidget(self.start_frame_count, 0, 1)
        range_layout.addWidget(QLabel("结束虚拟信道帧计数:"), 1, 0)
        range_layout.addWidget(self.end_frame_count, 1, 1)

        # 添加说明标签
        hint_label = QLabel("提示：请输入3字节（6位）十六进制数，如 03B64F")
        hint_label.setStyleSheet("color: gray; font-size: 10px;")
        range_layout.addWidget(hint_label, 2, 0, 1, 2)

        range_group.setLayout(range_layout)
        left_layout.addWidget(range_group)

        # 添加到左侧布局
        left_layout.addWidget(file_group)
        left_layout.addWidget(range_group)
        
        # 操作按钮
        button_layout = QHBoxLayout()
        self.compare_button = QPushButton("执行比对")
        self.compare_button.setEnabled(False)
        self.compare_button.setStyleSheet("""
            QPushButton {
                background-color: #0064c8;
                color: white;
                border: none;
                padding: 10px 20px;
                font-size: 14px;
                font-weight: bold;
                border-radius: 5px;
                min-width: 150px;
            }
            QPushButton:disabled {
                background-color: #cccccc;
            }
            QPushButton:hover:!disabled {
                background-color: #0055a5;
            }
            QPushButton:pressed:!disabled {
                background-color: #00448a;
            }
        """)

        button_layout.addStretch()
        button_layout.addWidget(self.compare_button)
        button_layout.addStretch()
        left_layout.addLayout(button_layout)

        # 创建右侧结果显示面板
        right_panel = QWidget()
        right_layout = QVBoxLayout()
        right_panel.setLayout(right_layout)
        # 为右侧面板设置弹性尺寸策略
        right_panel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # 比对结果显示区域
        result_group = QGroupBox("比对结果")
        result_layout = QVBoxLayout()

        # 结果统计
        self.summary_label = QLabel()
        self.summary_label.setStyleSheet("""
            QLabel {
                font-size: 12pt;
                padding: 10px;
                background-color: #f8f9fa;
                border-radius: 5px;
            }
        """)
        result_layout.addWidget(self.summary_label)

        # 差异表格
        self.diff_table = QTableWidget()
        self.diff_table.setColumnCount(2)
        self.diff_table.setHorizontalHeaderLabels(['帧计数', '比对结果'])
        # 设置表格为不可编辑状态
        self.diff_table.setEditTriggers(QAbstractItemView.NoEditTriggers)
        # 启用交替行颜色
        self.diff_table.setAlternatingRowColors(True)
        self.diff_table.setStyleSheet("""
            QTableWidget {
                gridline-color: #ddd;
                border: 1px solid #ddd;
                background-color: white;
                alternate-background-color: #E3F2FD;  /* 浅蓝色背景 */
                selection-background-color: #2196F3;  /* 选中时的深蓝色 */
                selection-color: white;
            }
            QHeaderView::section {
                background-color: #1976D2;  /* 深蓝色表头背景 */
                color: white;  /* 表头文字颜色 */
                padding: 6px;
                border: none;
                font-weight: bold;
            }
            QHeaderView::section:checked {
                background-color: #1565C0;  /* 选中时更深的蓝色 */
            }
        """)
        result_layout.addWidget(self.diff_table)
        
        # 添加分页控件
        self.pagination_widget = QWidget()
        pagination_layout = QHBoxLayout()
        pagination_layout.setSpacing(10)
        
        # 上一页按钮
        self.prev_page_btn = QPushButton("上一页")
        self.prev_page_btn.setEnabled(False)
        self.prev_page_btn.clicked.connect(self._go_to_prev_page)
        self.prev_page_btn.setMaximumWidth(100)
        pagination_layout.addWidget(self.prev_page_btn)
        
        # 添加伸展因子，使页码信息居中
        pagination_layout.addStretch()
        
        # 页码信息
        self.page_info_label = QLabel("第 1 页 / 共 1 页")
        self.page_info_label.setAlignment(Qt.AlignCenter)
        self.page_info_label.setStyleSheet("font-size: 12pt; padding: 5px;")
        pagination_layout.addWidget(self.page_info_label)
        
        # 添加伸展因子
        pagination_layout.addStretch()
        
        # 下一页按钮
        self.next_page_btn = QPushButton("下一页")
        self.next_page_btn.setEnabled(False)
        self.next_page_btn.clicked.connect(self._go_to_next_page)
        self.next_page_btn.setMaximumWidth(100)
        pagination_layout.addWidget(self.next_page_btn)
        
        self.pagination_widget.setLayout(pagination_layout)
        self.pagination_widget.setVisible(False)  # 初始隐藏
        result_layout.addWidget(self.pagination_widget)

        result_group.setLayout(result_layout)
        right_layout.addWidget(result_group)

        # 创建分割器，允许用户调整左右面板的大小
        self.splitter = QSplitter(Qt.Horizontal)
        self.splitter.addWidget(left_panel)
        self.splitter.addWidget(right_panel)
        
        # 为分割器设置大小策略，使其填充整个可用空间
        self.splitter.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        
        # 设置左右面板的初始宽度比例
        self.splitter.setSizes([400, 600])
        
        # 将分割器添加到主布局，确保其占据所有可用空间
        self.layout.addWidget(self.splitter, 1)  # 添加伸展因子1

        self.setLayout(self.layout)

        # 连接信号
        self.compare_button.clicked.connect(self._on_compare_clicked)

        # 文件路径变化时更新比对按钮状态和帧计数范围
        self.file1_path.textChanged.connect(self._update_compare_button_state)
        self.file2_path.textChanged.connect(self._update_compare_button_state)
        self.file1_path.textChanged.connect(self._update_frame_count_range)
        self.file2_path.textChanged.connect(self._update_frame_count_range)
        self.convert_button.clicked.connect(self._convert_frame_data)

        # 连接文件路径变化信号
        self.source_file_path.textChanged.connect(self._update_convert_button_state)
        self.target_folder_path.textChanged.connect(self._update_convert_button_state)

        # 添加连接表格双击事件的代码
        self.diff_table.itemDoubleClicked.connect(self._show_detailed_diff)
        
        # 连接自定义转换选项的切换信号
        self.convert_custom_radio.toggled.connect(self._toggle_custom_range)
        self.custom_start_byte.textChanged.connect(self._update_convert_button_state)
        self.custom_end_byte.textChanged.connect(self._update_convert_button_state)
        
    # 切换自定义范围输入框的显示状态
    def _toggle_custom_range(self, checked):
        """显示或隐藏自定义范围输入框"""
        self.custom_range_widget.setVisible(checked)
        self._update_convert_button_state()

    def _update_convert_button_state(self):
        """更新转换按钮状态"""
        has_both_paths = bool(self.source_file_path.text() and self.target_folder_path.text())
        
        # 如果选择了自定义范围，检查是否输入了有效的范围
        if self.convert_custom_radio.isChecked():
            has_valid_range = bool(self.custom_start_byte.text() and self.custom_end_byte.text())
            self.convert_button.setEnabled(has_both_paths and has_valid_range)
        else:
            self.convert_button.setEnabled(has_both_paths)

        # ---------- 内存优化辅助方法 ----------
    # ---------- 内存优化辅助方法 ----------
    def _strip_raw_frames(self, frames):
        """删除帧列表中的 raw_frame 字段以降低内存占用"""
        removed = 0
        for frame in frames:
            if isinstance(frame, dict) and 'raw_frame' in frame:
                frame.pop('raw_frame', None)
                removed += 1
        if removed:
            self.logger.info(f"已移除 {removed} 个 raw_frame 字段")
            gc.collect()
    # 添加新方法 - 显示详细差异对话框
    def _show_detailed_diff(self, item):
        """弹窗显示比对详情（已废弃，移除弹窗功能）"""
        pass

    def _on_compare_clicked(self):
        """执行比对操作"""
        try:
            self._clear_results()

            # 获取文件路径
            file1_path = self.file1_path.text()
            file2_path = self.file2_path.text()

            if not (file1_path and file2_path):
                QMessageBox.warning(self, "警告", "请选择两个需要比对的文件")
                return

            # 获取文件格式选择
            file1_format = self._get_selected_format(1)
            file2_format = self._get_selected_format(2)

            # 获取帧计数范围（现在是虚拟信道帧计数范围）
            start_count = None
            end_count = None

            # 解析十六进制输入
            if self.start_frame_count.text():
                try:
                    start_count = int(self.start_frame_count.text(), 16)
                except ValueError:
                    QMessageBox.warning(self, "警告", f"无效的起始虚拟信道帧计数: {self.start_frame_count.text()}")
                    return
                    
            if self.end_frame_count.text():
                try:
                    end_count = int(self.end_frame_count.text(), 16)
                except ValueError:
                    QMessageBox.warning(self, "警告", f"无效的结束虚拟信道帧计数: {self.end_frame_count.text()}")
                    return

            # 验证虚拟信道帧计数范围
            if start_count is not None and end_count is not None and start_count > end_count:
                QMessageBox.warning(self, "警告", "起始虚拟信道帧计数不能大于结束虚拟信道帧计数")
                return

            # 创建进度对话框
            progress = ProgressDialog(self)
            progress.setWindowTitle("正在比对文件")
            progress.show()

            # 保存比对参数
            self.compare_params = {
                'file1_path': file1_path,
                'file2_path': file2_path,
                'file1_format': file1_format,
                'file2_format': file2_format,
                'start_count': start_count,
                'end_count': end_count,
                'frames1': None,
                'frames2': None
            }

            # 创建文件1加载线程 - 使用多格式加载器
            self.loader_thread1 = MultiFormatFileLoaderThread(file1_path, file1_format)

            # 连接信号
            self.loader_thread1.progress_signal.connect(
                lambda value, status, detail: progress.update_progress(int(value * 0.4), f"文件1: {status}", detail)
            )

            # 处理文件1加载完成
            def on_file1_loaded(frames):
                # 优化内存使用
                self._strip_raw_frames(frames)
                self.compare_params['frames1'] = frames

                # 开始加载文件2 - 使用多格式加载器
                self.loader_thread2 = MultiFormatFileLoaderThread(file2_path, file2_format)

                # 连接信号
                self.loader_thread2.progress_signal.connect(
                    lambda value, status, detail: progress.update_progress(40 + int(value * 0.4), f"文件2: {status}",
                                                                           detail)
                )

                # 处理文件2加载完成
                def on_file2_loaded(frames):
                    # 优化内存使用
                    self._strip_raw_frames(frames)
                    self.compare_params['frames2'] = frames

                    # 执行比对
                    self._perform_comparison(progress)

                # 处理文件2加载错误
                def on_file2_error(error_msg):
                    progress.close()
                    QMessageBox.critical(self, "错误", f"加载文件2失败: {error_msg}")

                # 连接信号
                self.loader_thread2.finished_signal.connect(on_file2_loaded)
                self.loader_thread2.error_signal.connect(on_file2_error)

                # 开始加载文件2
                self.loader_thread2.start()

            # 处理文件1加载错误
            def on_file1_error(error_msg):
                progress.close()
                QMessageBox.critical(self, "错误", f"加载文件1失败: {error_msg}")

            # 处理取消操作
            def on_cancel_requested():
                if hasattr(self, 'loader_thread1') and self.loader_thread1.isRunning():
                    self.loader_thread1.cancel()
                if hasattr(self, 'loader_thread2') and self.loader_thread2.isRunning():
                    self.loader_thread2.cancel()

            # 连接信号
            self.loader_thread1.finished_signal.connect(on_file1_loaded)
            self.loader_thread1.error_signal.connect(on_file1_error)
            progress.canceled.connect(on_cancel_requested)

            # 开始加载文件1
            self.loader_thread1.start()

        except Exception as e:
            self.logger.error(f"执行比对失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"执行比对失败: {str(e)}")

    @safe_compare_decorator
    def _perform_comparison(self, progress):
        """执行文件比对操作"""
        try:
            # 检查内存状态
            if HAS_PSUTIL:
                memory = psutil.virtual_memory()
                if memory.percent > 90:
                    gc.collect()
                    if psutil.virtual_memory().percent > 90:
                        raise MemoryError(f"内存使用率过高({memory.percent:.1f}%)，无法继续比对")
            
            # 获取比对参数
            frames1 = self.compare_params['frames1']
            frames2 = self.compare_params['frames2']
            # 优化内存使用
            self._strip_raw_frames(frames1)
            self._strip_raw_frames(frames2)
            file1_path = self.compare_params['file1_path']
            file2_path = self.compare_params['file2_path']
            file1_format = self.compare_params.get('file1_format', '1092')
            file2_format = self.compare_params.get('file2_format', '1092')
            start_count = self.compare_params['start_count']
            end_count = self.compare_params['end_count']
            
            # 添加格式兼容性检查
            if file1_format != file2_format:
                # 获取比对范围
                compare_range_str = self._get_compare_range_description()
                
                # 特别检查比对1024字节和896字节格式的情况
                if (file1_format == '1024' and file2_format == '896') or \
                   (file1_format == '896' and file2_format == '1024'):
                    if self.compare_1024_radio.isChecked():
                        # 如果选择比对1024字节，但其中一个文件是896字节格式
                        self.logger.warning(f"比对不同格式文件: {file1_format}字节 vs {file2_format}字节")
                        # 自动调整比对范围为896字节
                        QMessageBox.information(
                            self, 
                            "格式兼容性提示",
                            f"您正在比对{file1_format}字节和{file2_format}字节格式的文件。\n"
                            f"由于896字节格式文件数据较少，系统将自动调整比对范围为896字节。\n"
                            f"这可能会导致部分数据（897-1024字节）无法比对。"
                        )
                        # 强制设置比对范围为896字节
                        self.compare_896_radio.setChecked(True)
                else:
                    # 其他格式组合的提示
                    self.logger.info(f"比对不同格式文件: {file1_format}字节 vs {file2_format}字节")

            progress.update_progress(80, "正在比对文件...", "使用Cython快速过滤帧数据")

            # 根据虚拟信道帧计数范围过滤帧
            if start_count is not None or end_count is not None:
                start_str = f'{start_count:X}' if start_count is not None else 'N/A'
                end_str = f'{end_count:X}' if end_count is not None else 'N/A'
                self.logger.info(f"根据虚拟信道帧计数范围过滤: {start_str}-{end_str}")
                try:
                    # 使用Cython引擎快速过滤
                    cython_engine = get_cython_engine()
                    if cython_engine and cython_engine.is_available():
                        # 使用Cython快速提取虚拟信道帧计数
                        _, vc_counts1 = cython_engine.extract_virtual_channel_info_fast(frames1, file1_format)
                        _, vc_counts2 = cython_engine.extract_virtual_channel_info_fast(frames2, file2_format)
                        
                        # 高效过滤
                        valid_indices1 = [i for i, count in enumerate(vc_counts1) 
                                        if (start_count is None or count >= start_count) and 
                                           (end_count is None or count <= end_count)]
                        valid_indices2 = [i for i, count in enumerate(vc_counts2) 
                                        if (start_count is None or count >= start_count) and 
                                           (end_count is None or count <= end_count)]
                        
                        frames1 = [frames1[i] for i in valid_indices1]
                        frames2 = [frames2[i] for i in valid_indices2]
                        
                        self.logger.info(f"Cython过滤后: 文件1剩余{len(frames1)}帧, 文件2剩余{len(frames2)}帧")
                    else:
                        # Cython不可用，使用优化的NumPy方法
                        self.logger.warning("Cython不可用，使用优化的NumPy过滤")
                        numpy_comparer = OptimizedNumpyComparer()
                        
                        # 提取虚拟信道信息
                        _, vc_counts1 = numpy_comparer.extract_vc_info_vectorized(frames1, file1_format)
                        _, vc_counts2 = numpy_comparer.extract_vc_info_vectorized(frames2, file2_format)
                        
                        # 使用NumPy高效过滤
                        frames1 = numpy_comparer.filter_frames_by_count_range(frames1, vc_counts1, start_count, end_count)
                        frames2 = numpy_comparer.filter_frames_by_count_range(frames2, vc_counts2, start_count, end_count)
                        
                        self.logger.info(f"NumPy过滤后: 文件1剩余{len(frames1)}帧, 文件2剩余{len(frames2)}帧")
                except Exception as e:
                    self.logger.error(f"快速过滤失败，回退到标准方法: {e}")
                    # 回退到原始过滤方法
                    frames1 = self._filter_frames_by_count_range(frames1, start_count, end_count, file1_format)
                    frames2 = self._filter_frames_by_count_range(frames2, start_count, end_count, file2_format)
            else:
                # 原始过滤方法
                frames1 = self._filter_frames_by_count_range(frames1, start_count, end_count, file1_format)
                frames2 = self._filter_frames_by_count_range(frames2, start_count, end_count, file2_format)

            # 获取两个文件中的帧计数
            # 使用Python内置类型而不是NumPy数组
            frame_counts1 = {int(frame['frame_count']) for frame in frames1}
            frame_counts2 = {int(frame['frame_count']) for frame in frames2}

            # 找出共同的帧计数
            common_frame_counts = frame_counts1.intersection(frame_counts2)

            # 过滤出共同帧计数的帧
            filtered_frames1 = [frame for frame in frames1 if int(frame['frame_count']) in common_frame_counts]
            filtered_frames2 = [frame for frame in frames2 if int(frame['frame_count']) in common_frame_counts]

            progress.update_progress(85, "正在比对文件...", f"比对 {len(filtered_frames1)} 帧")

            # 确定比对范围
            compare_range = None
            if self.compare_896_radio.isChecked():
                # 仅比对f896数据区(896字节)
                compare_range = (0, 895)
            # 如果选择1024字节，默认比对全部，不需要设置compare_range

            # 创建多格式处理器来进行比对
            multi_processor = MultiFormatFrameProcessor()
            
            # 使用按虚拟信道分组的比对方法
            comparison_result = self._compare_frames_by_virtual_channel(
                filtered_frames1,
                filtered_frames2,
                file1_format,
                compare_range,
                progress
            )

            progress.update_progress(95, "正在生成显示...", "更新界面")

            # 更新界面显示
            self._update_comparison_display(comparison_result)

            progress.update_progress(100, "比对完成")
            # 延迟关闭进度对话框，确保界面渲染完成
            progress.complete_and_close()

        except Exception as e:
            progress.close()
            self.logger.error(f"执行比对失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"执行比对失败: {str(e)}")

    def _update_comparison_display(self, comparison_result):
        """更新比对结果显示 - 分页版本"""
        try:
            # 清空现有内容
            self._clear_results()

            # 获取虚拟信道结果
            vc_results = comparison_result.get('virtual_channel_results', {})
            
            # 计算总体统计信息
            total_frames1 = comparison_result['total_frames'][0]
            total_frames2 = comparison_result['total_frames'][1]
            total_matching = comparison_result.get('matching_frames', 0)
            total_mismatching = 0
            total_missing_in_target = 0
            total_missing_in_base = 0
            
            # 统计各类型的帧数，容错处理缺失字段
            for vc_id, vc_result in vc_results.items():
                total_mismatching += vc_result.get('mismatching_frames', 0)
                total_missing_in_target += vc_result.get('missing_in_target', 0)
                total_missing_in_base += vc_result.get('missing_in_base', 0)
            
            # 获取比对范围信息
            compare_mode = self._get_compare_range_description()

            # 构建统计摘要
            summary_lines = [
                f"比对范围：{compare_mode}",
                f"基准文件总帧数：{total_frames1}",
                f"目标文件总帧数：{total_frames2}",
                f"虚拟信道数量：{len(vc_results)}",
                "",
                "总体比对结果：",
                f"  • 完全匹配：{total_matching} 帧",
                f"  • 内容不匹配：{total_mismatching} 帧",
                f"  • 目标文件缺失：{total_missing_in_target} 帧",
                f"  • 基准文件缺失：{total_missing_in_base} 帧"
            ]
            
            self.summary_label.setText("\n".join(summary_lines))

            # 更新差异表格 - 添加虚拟信道列
            self.diff_table.setColumnCount(4)
            self.diff_table.setHorizontalHeaderLabels(['虚拟信道', '虚拟信道帧计数', '比对结果', '差异详情'])
            
            # 收集所有需要显示的行数据（只收集差异）
            self.all_rows_data = []
            total_differences = 0
            SHOW_ONLY_DIFFERENCES = True  # 只显示差异，不显示匹配的帧
            
            # 按虚拟信道ID排序显示
            for vc_id in sorted(vc_results.keys()):
                vc_result = vc_results[vc_id]
                
                # 如果当前虚拟信道结果缺少详细比较数据，则跳过，避免KeyError
                if 'frame_comparisons' not in vc_result:
                    # 记录日志方便排查
                    self.logger.warning(f"虚拟信道 {vc_id} 结果缺少 frame_comparisons 字段，已跳过")
                    continue
                
                # 按帧计数排序该虚拟信道的比对结果
                sorted_comparisons = sorted(vc_result['frame_comparisons'], 
                                          key=lambda x: x['frame_count'])
                
                for frame_result in sorted_comparisons:
                    # 如果只显示差异，跳过匹配的帧
                    if SHOW_ONLY_DIFFERENCES and frame_result['type'] == 'matching':
                        continue
                    
                    total_differences += 1
                    
                    # 收集行数据
                    row_data = {
                        'vc_id': vc_id,
                        'frame_result': frame_result,
                        'frame_count': frame_result['frame_count']
                    }
                    self.all_rows_data.append(row_data)
            
            # 计算总页数
            self.total_pages = max(1, (len(self.all_rows_data) + self.page_size - 1) // self.page_size)
            self.current_page = 1
            self.page_cache = {}  # 清空页面缓存
            
            # 保存当前比对结果
            self.current_comparison = comparison_result
            
            # 显示分页控件
            if self.total_pages > 1:
                self.pagination_widget.setVisible(True)
                self._update_pagination_controls()
            else:
                self.pagination_widget.setVisible(False)
            
            # 显示第一页数据
            self._display_page(1)
            
            # 更新统计信息，添加差异总数和分页信息
            if total_differences > 0:
                summary_lines.append("")
                summary_lines.append(f"共有 {total_differences} 个差异")
                if self.total_pages > 1:
                    summary_lines.append(f"分页显示：每页 {self.page_size} 条，共 {self.total_pages} 页")
                self.summary_label.setText("\n".join(summary_lines))

            self.logger.info(f"成功更新比对结果显示，共 {total_differences} 个差异，分 {self.total_pages} 页")

        except Exception as e:
            self.logger.error(f"更新比对结果显示失败: {str(e)}")
            raise

    def _update_compare_button_state(self):
        """更新比对按钮状态"""
        has_both_files = bool(self.file1_path.text() and self.file2_path.text())
        self.compare_button.setEnabled(has_both_files)

    def _clear_results(self):
        """清空比对结果"""
        self.summary_label.clear()
        self.diff_table.clearContents()
        self.diff_table.setRowCount(0)
        
        # 重置分页相关变量
        self.current_page = 1
        self.total_pages = 1
        self.all_rows_data = []
        self.page_cache = {}
        self.pagination_widget.setVisible(False)
    
    def _get_compare_range_description(self):
        """获取当前比对范围的描述"""
        if self.compare_1024_radio.isChecked():
            return "1024字节 (f896数据区 + f128数据区)"
        else:
            return "896字节 (仅f896数据区)"

    def _select_file(self, file_num):
        """选择文件"""
        file_title = "选择基准文件" if file_num == 1 else "选择目标文件"
        file_path, _ = QFileDialog.getOpenFileName(
            self,
            file_title,
            "",
            "帧数据文件 (*.raw *.dat);;XML文件 (*.xml);;所有文件 (*.*)"
        )
        if file_path:
            if file_num == 1:
                self.file1_path.setText(file_path)
            else:
                self.file2_path.setText(file_path)

            # 若源文件超过 1GB，仅记录日志，不再弹窗提示
            file_size = os.path.getsize(file_path)
            if file_size > 1 * 1024 * 1024 * 1024:
                size_gb = file_size / (1024 * 1024 * 1024)
                self.logger.info(
                    f"选择了大文件 (≈{size_gb:.2f} GB) 进行转换，系统将自动采用优化流程，无弹窗提示"
                )

    def _update_frame_count_range(self):
        """更新帧计数范围"""
        try:
            file1_path = self.file1_path.text()
            file2_path = self.file2_path.text()

            if file1_path and file2_path:
                # 获取文件格式选择
                file1_format = self._get_selected_format(1)
                file2_format = self._get_selected_format(2)
                
                # 创建进度对话框
                progress = ProgressDialog(self)
                progress.setWindowTitle("读取文件")
                progress.show()

                # 首先读取第一个文件 - 使用多格式加载器
                self.loader_thread1 = MultiFormatFileLoaderThread(file1_path, file1_format)

                # 连接信号
                self.loader_thread1.progress_signal.connect(
                    lambda value, status, detail: progress.update_progress(int(value * 0.4), f"文件1: {status}", detail)
                )

                # 处理文件1加载完成
                def on_file1_loaded(frames1):
                    # 开始加载文件2 - 使用多格式加载器
                    self.loader_thread2 = MultiFormatFileLoaderThread(file2_path, file2_format)

                    # 连接信号
                    self.loader_thread2.progress_signal.connect(
                        lambda value, status, detail: progress.update_progress(40 + int(value * 0.4), f"文件2: {status}", detail)
                    )

                    # 处理文件2加载完成
                    def on_file2_loaded(frames2):
                        try:
                            # 从两个文件中提取虚拟信道帧计数并转换为集合
                            from frame_processor import FrameProcessor
                            
                            vc_frame_counts1 = set()
                            vc_frame_counts2 = set()
                            
                            # 提取虚拟信道帧计数
                            for frame in frames1:
                                vc_count = FrameProcessor.extract_virtual_channel_frame_count(frame)
                                if vc_count > 0:  # 只添加有效的虚拟信道帧计数
                                    vc_frame_counts1.add(vc_count)
                            
                            for frame in frames2:
                                vc_count = FrameProcessor.extract_virtual_channel_frame_count(frame)
                                if vc_count > 0:  # 只添加有效的虚拟信道帧计数
                                    vc_frame_counts2.add(vc_count)

                            # 找出共同的虚拟信道帧计数并排序
                            common_vc_counts = sorted(vc_frame_counts1.intersection(vc_frame_counts2))

                            progress.update_progress(90, f"正在处理共同虚拟信道帧计数: {len(common_vc_counts)}...")

                            # 验证找到的共同虚拟信道帧计数
                            if common_vc_counts:
                                # 设置第一个和最后一个共同虚拟信道帧计数（十六进制格式）
                                first_common = common_vc_counts[0]
                                last_common = common_vc_counts[-1]
                                
                                # 格式化为6位十六进制（不带0x前缀）
                                self.start_frame_count.setText(f"{first_common:06X}")
                                self.end_frame_count.setText(f"{last_common:06X}")
                            else:
                                # 如果没有共同虚拟信道帧计数，清空输入框
                                self.start_frame_count.clear()
                                self.end_frame_count.clear()

                            progress.update_progress(100, "处理完成")
                            progress.complete_and_close()

                        except Exception as e:
                            self.logger.error(f"处理虚拟信道帧计数范围失败: {str(e)}")
                            progress.close()
                            # 发生错误时清空输入框
                            self.start_frame_count.clear()
                            self.end_frame_count.clear()

                    # 处理文件2加载错误
                    def on_file2_error(error_msg):
                        progress.close()
                        self.logger.error(f"加载文件2失败: {error_msg}")
                        # 清空输入框
                        self.start_frame_count.clear()
                        self.end_frame_count.clear()

                    # 连接信号
                    self.loader_thread2.finished_signal.connect(on_file2_loaded)
                    self.loader_thread2.error_signal.connect(on_file2_error)

                    # 开始加载文件2
                    self.loader_thread2.start()

                # 处理文件1加载错误
                def on_file1_error(error_msg):
                    progress.close()
                    self.logger.error(f"加载文件1失败: {error_msg}")
                    # 清空输入框
                    self.start_frame_count.clear()
                    self.end_frame_count.clear()

                # 处理取消操作
                def on_cancel_requested():
                    if hasattr(self, 'loader_thread1') and self.loader_thread1.isRunning():
                        self.loader_thread1.cancel()
                    if hasattr(self, 'loader_thread2') and self.loader_thread2.isRunning():
                        self.loader_thread2.cancel()
                    # 清空输入框
                    self.start_frame_count.clear()
                    self.end_frame_count.clear()

                # 连接信号
                self.loader_thread1.finished_signal.connect(on_file1_loaded)
                self.loader_thread1.error_signal.connect(on_file1_error)
                progress.canceled.connect(on_cancel_requested)

                # 开始加载文件1
                self.loader_thread1.start()

        except Exception as e:
            self.logger.error(f"更新帧计数范围失败: {str(e)}")
            # 发生错误时清空输入框
            self.start_frame_count.clear()
            self.end_frame_count.clear()

    def _select_convert_file(self, file_type):
        """选择转换文件或文件夹"""
        if file_type == 'source':
            file_path, _ = QFileDialog.getOpenFileName(
                self,
                "选择源文件",
                "",
                "帧数据文件 (*.raw *.dat);;XML文件 (*.xml);;所有文件 (*.*)"
            )
            if file_path:
                self.source_file_path.setText(file_path)

                # 检查文件大小并显示提示
                file_size = os.path.getsize(file_path)
                if file_size > 1 * 1024 * 1024 * 1024:
                    size_gb = file_size / (1024 * 1024 * 1024)
                    # 记录日志，无弹窗提示
                    self.logger.info(
                        f"选择了大文件 (≈{size_gb:.2f} GB) 进行转换，将自动启用优化流程")
        else:  # target
            folder_path = QFileDialog.getExistingDirectory(
                self,
                "选择目标文件夹",
                "",
                QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks
            )
            if folder_path:
                self.target_folder_path.setText(folder_path)

        # 更新转换按钮状态
        self._update_convert_button_state()

    def _convert_frame_data(self):
        """执行帧数据转换 - 增强版本，支持高性能向量化操作"""
        try:
            source_path = self.source_file_path.text()
            target_folder = self.target_folder_path.text()

            if not (source_path and target_folder):
                QMessageBox.warning(self, "警告", "请选择源文件和目标文件夹")
                return

            # 获取文件信息
            file_size = os.path.getsize(source_path)
            
            # 初始化高性能转换器
            fast_converter = FastFrameConverter()
            
            # 确定转换模式
            if self.convert_1024_radio.isChecked():
                extract_mode = '1024'
                custom_range = None
            elif self.convert_896_radio.isChecked():
                extract_mode = '896'
                custom_range = None
            elif self.convert_custom_radio.isChecked():
                extract_mode = 'custom'
                try:
                    start_byte = int(self.custom_start_byte.text())
                    end_byte = int(self.custom_end_byte.text())
                    custom_range = (start_byte, end_byte)
                except ValueError:
                    QMessageBox.warning(self, "警告", "无效的自定义范围")
                    return
            else:
                QMessageBox.warning(self, "警告", "请选择一个转换选项")
                return

            # 生成目标文件路径
            source_filename = os.path.basename(source_path)
            
            if extract_mode == '1024':
                target_filename = f"{os.path.splitext(source_filename)[0]}_1024{os.path.splitext(source_filename)[1]}"
            elif extract_mode == '896':
                target_filename = f"{os.path.splitext(source_filename)[0]}_896{os.path.splitext(source_filename)[1]}"
            else:  # custom
                start_byte, end_byte = custom_range
                target_filename = f"{os.path.splitext(source_filename)[0]}_custom_{start_byte}_to_{end_byte}{os.path.splitext(source_filename)[1]}"
            
            target_path = os.path.join(target_folder, target_filename)

            # 创建进度对话框
            progress = ProgressDialog(self)
            progress.setWindowTitle("转换帧数据")
            progress.show()

            try:
                # 直接使用高性能向量化方法（默认处理方式）
                self._convert_with_vectorized_method(
                    source_path, target_path, extract_mode, custom_range, progress
                )

            finally:
                progress.close()

        except Exception as e:
            self.logger.error(f"转换帧数据失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"转换帧数据失败: {str(e)}")

    def _convert_with_vectorized_method(self, source_path, target_path, extract_mode, custom_range, progress):
        """使用向量化方法进行转换"""
        try:
            fast_converter = FastFrameConverter()
            
            # 创建进度回调函数
            def progress_callback(percent, status, detail=""):
                progress.update_progress(percent, status, detail)
                QApplication.processEvents()  # 确保UI响应
                
                # 检查是否取消 - 修复属性名
                if progress.is_cancelled:
                    raise Exception("用户取消了转换操作")

            # 执行向量化转换
            result = fast_converter.convert_frames_vectorized(
                source_path=source_path,
                target_path=target_path,
                extract_mode=extract_mode,
                custom_range=custom_range,
                progress_callback=progress_callback,
                chunk_size_mb=100  # 100MB块大小，可根据系统内存调整
            )
            
            # 验证转换结果
            progress.update_progress(95, "验证转换结果", "采样验证数据正确性...")
            verification = fast_converter.verify_conversion(
                source_path, target_path, extract_mode, custom_range, sample_frames=50
            )
            
            progress.update_progress(100, "转换完成")
            
            # 显示结果
            success_msg = (
                f"高性能向量化转换完成！\n\n"
                f"转换统计:\n"
                f"• 源文件: {os.path.basename(source_path)}\n"
                f"• 目标文件: {os.path.basename(target_path)}\n"
                f"• 处理帧数: {result['total_frames']:,}\n"
                f"• 转换模式: {self._get_convert_range_description()}\n"
                f"• 处理时间: {result['elapsed_time']:.2f} 秒\n"
                f"• 处理速度: {result['throughput_mbps']:.1f} MB/s\n"
                f"• 源文件大小: {result['source_size_mb']:.1f} MB\n"
                f"• 目标文件大小: {result['target_size_mb']:.1f} MB\n\n"
                f"验证结果:\n"
                f"• 验证状态: {'通过' if verification['valid'] else '失败'}\n"
                f"• 验证帧数: {verification.get('verified_frames', 0)}\n"
                f"• 成功率: {verification.get('success_rate', 0):.1f}%"
            )
            
            if verification['valid']:
                QMessageBox.information(self, "转换成功", success_msg)
            else:
                QMessageBox.warning(self, "转换警告", 
                                  success_msg + f"\n\n验证错误: {verification.get('error', '未知错误')}")
            
        except Exception as e:
            if "用户取消" not in str(e):
                self.logger.error(f"向量化转换失败: {str(e)}")
            raise

    def _convert_with_traditional_method(self, source_path, target_path, extract_mode, custom_range, progress):
        """使用传统方法进行转换（原有实现的优化版本）"""
        try:
            # 读取源文件
            with open(source_path, 'rb') as f:
                source_data = f.read()

            # 检查文件大小是否为1092的整数倍
            if len(source_data) % 1092 != 0:
                raise ValueError(f"源文件大小({len(source_data)}字节)不是1092的整数倍")

            # 计算帧数
            frame_count = len(source_data) // 1092
            progress.update_progress(20, f"读取到{frame_count}帧数据（传统方法）...")

            # 确定提取参数
            if extract_mode == '1024':
                extract_range = (64, 1088)  # f896+f128
                output_size = 1024
            elif extract_mode == '896':
                extract_range = (64, 960)   # 仅f896
                output_size = 896
            else:  # custom
                start_byte, end_byte = custom_range
                extract_range = (start_byte, end_byte + 1)
                output_size = end_byte - start_byte + 1

            # 打开目标文件并逐帧处理
            with open(target_path, 'wb') as f:
                for i in range(frame_count):
                    # 检查取消状态 - 修复属性名
                    if progress.is_cancelled:
                        raise Exception("用户取消了转换操作")
                    
                    # 计算进度百分比
                    percent = 20 + (i * 70 // frame_count)
                    
                    # 每处理1000帧或最后一帧时更新进度
                    if i % 1000 == 0 or i == frame_count - 1:
                        progress.update_progress(
                            percent,
                            "正在转换帧数据（传统方法）",
                            f"正在处理第{i + 1}/{frame_count}帧..."
                        )
                        QApplication.processEvents()

                    # 提取当前帧的指定数据区
                    frame_start = i * 1092
                    start_byte, end_byte = extract_range
                    vcdu_data = source_data[frame_start + start_byte:frame_start + end_byte]

                    # 写入目标文件
                    f.write(vcdu_data)

            progress.update_progress(100, "传统方法转换完成")

            # 显示成功消息（传统方法）
            QMessageBox.information(
                self,
                "成功",
                f"传统方法转换完成！\n"
                f"源文件: {os.path.basename(source_path)}\n"
                f"目标文件: {os.path.basename(target_path)}\n"
                f"共处理{frame_count}帧数据\n"
                f"转换模式: {self._get_convert_range_description()}\n"
                f"源文件大小: {len(source_data):,}字节\n"
                f"目标文件大小: {frame_count * output_size:,}字节"
            )

        except Exception as e:
            if "用户取消" not in str(e):
                self.logger.error(f"传统转换失败: {str(e)}")
            raise

    def _get_convert_range_description(self):
        """获取当前转换范围的描述"""
        if self.convert_1024_radio.isChecked():
            return "1024字节 (f896数据区 + f128数据区)"
        elif self.convert_896_radio.isChecked():
            return "896字节 (仅f896数据区)"
        else:
            try:
                start_byte = self.custom_start_byte.text()
                end_byte = self.custom_end_byte.text()
                if not start_byte or not end_byte:
                    return "自定义范围 (未设置)"
                range_size = int(end_byte) - int(start_byte) + 1
                return f"自定义范围 ({range_size}字节, 位置{start_byte}-{end_byte})"
            except (ValueError, TypeError):
                return "自定义范围 (无效输入)"

    def _get_selected_format(self, file_num):
        """获取选中的文件格式
        
        Args:
            file_num: 文件编号 (1 或 2)
            
        Returns:
            str: 格式字符串 ('1092', '1024', '896')
        """
        if file_num == 1:
            if self.file1_1092_radio.isChecked():
                return '1092'
            elif self.file1_1024_radio.isChecked():
                return '1024'
            elif self.file1_896_radio.isChecked():
                return '896'
        else:  # file_num == 2
            if self.file2_1092_radio.isChecked():
                return '1092'
            elif self.file2_1024_radio.isChecked():
                return '1024'
            elif self.file2_896_radio.isChecked():
                return '896'
        
        # 默认返回1092
        return '1092'

    def _compare_frames_multi_format(self, frames1, frames2, file1_path, file2_path, 
                                   file1_format, file2_format, compare_range, processor):
        """支持多格式的帧比对方法
        
        Args:
            frames1: 文件1的帧列表
            frames2: 文件2的帧列表
            file1_path: 文件1路径
            file2_path: 文件2路径
            file1_format: 文件1格式 ('1092', '1024', '896')
            file2_format: 文件2格式 ('1092', '1024', '896')
            compare_range: 比对范围
            processor: 多格式处理器实例
            
        Returns:
            比对结果字典
        """
        try:
            # 初始化比对结果
            comparison = {
                'total_frames': [len(frames1), len(frames2)],
                'frame_results': [],
                'matching_frames': 0,
                'frames1': frames1,
                'frames2': frames2,
                'file1_format': file1_format,
                'file2_format': file2_format
            }
            
            # 创建帧计数到帧的映射
            frames1_dict = {int(frame['frame_count']): frame for frame in frames1}
            frames2_dict = {int(frame['frame_count']): frame for frame in frames2}
            
            # 遍历所有共同的帧计数
            common_frame_counts = sorted(set(frames1_dict.keys()) & set(frames2_dict.keys()))
            self.logger.info(f"开始比对 {len(common_frame_counts)} 个共同帧计数 (格式: {file1_format} vs {file2_format})")
            
            # 定义报告差异数量的限制
            MAX_DIFF_REPORTS = 100
            
            for idx, frame_count in enumerate(common_frame_counts):
                if idx % 1000 == 0:
                    self.logger.debug(f"正在比对帧计数 {frame_count} (进度 {idx}/{len(common_frame_counts)})")
                    
                frame1 = frames1_dict[frame_count]
                frame2 = frames2_dict[frame_count]
                
                # 比较帧内容
                differences = []
                
                # 比较虚拟信道（如果两个格式都有）
                if 'virtual_channel' in frame1 and 'virtual_channel' in frame2:
                    if frame1['virtual_channel'] != frame2['virtual_channel']:
                        differences.append({
                            'field': 'virtual_channel',
                            'value1': int(frame1['virtual_channel']),
                            'value2': int(frame2['virtual_channel'])
                        })
                
                # 比较译码状态（如果两个格式都有）
                if 'decode_status' in frame1 and 'decode_status' in frame2:
                    if frame1['decode_status'] != frame2['decode_status']:
                        differences.append({
                            'field': 'decode_status',
                            'value1': int(frame1['decode_status']),
                            'value2': int(frame2['decode_status'])
                        })
                
                # 使用多格式处理器提取用于比对的数据
                data1 = processor.extract_comparison_data(frame1, compare_range)
                data2 = processor.extract_comparison_data(frame2, compare_range)
                
                # 比较提取的数据
                if len(data1) != len(data2):
                    differences.append({
                        'field': 'payload',
                        'differences': [{
                            'type': 'length_mismatch',
                            'length1': len(data1),
                            'length2': len(data2)
                        }]
                    })
                else:
                    # 使用NumPy进行快速比较
                    import numpy as np
                    arr1 = np.frombuffer(data1, dtype=np.uint8)
                    arr2 = np.frombuffer(data2, dtype=np.uint8)
                    
                    if not np.array_equal(arr1, arr2):
                        payload_diffs = []
                        diff_indices = np.where(arr1 != arr2)[0]
                        
                        # 限制报告的差异数量
                        reported_diff_count = 0
                        for index in diff_indices:
                            if reported_diff_count >= MAX_DIFF_REPORTS:
                                payload_diffs.append({
                                    'type': 'too_many_diffs',
                                    'limit': MAX_DIFF_REPORTS
                                })
                                break
                                
                            # 计算在原始数据中的实际位置
                            if compare_range:
                                actual_position = compare_range[0] + int(index)
                            else:
                                actual_position = int(index)
                                
                            payload_diffs.append({
                                'byte_position': actual_position,
                                'value1': int(arr1[index]),
                                'value2': int(arr2[index]),
                                'diff_bits': bin(int(arr1[index]) ^ int(arr2[index]))[2:].zfill(8)
                            })
                            reported_diff_count += 1
                            
                        if payload_diffs:
                            differences.append({
                                'field': 'payload',
                                'differences': payload_diffs
                            })
                
                # 添加比对结果
                if differences:
                    comparison['frame_results'].append({
                        'frame_count': int(frame_count),
                        'type': 'content_mismatch',
                        'differences': differences
                    })
                else:
                    comparison['frame_results'].append({
                        'frame_count': int(frame_count),
                        'type': 'matching'
                    })
                    comparison['matching_frames'] += 1
                    
            self.logger.info(f"多格式比对完成，匹配帧数: {comparison['matching_frames']}/{len(common_frame_counts)}")
            return comparison
            
        except Exception as e:
            self.logger.error(f"多格式比对失败: {str(e)}", exc_info=True)
            raise

    def _compare_frames_by_virtual_channel(self, frames1, frames2, frame_format, 
                                         compare_range, progress, base_progress=85):
        """按虚拟信道比对帧"""
        try:
            # 尝试使用Cython增强比对器
            cython_engine = get_cython_engine()
            if cython_engine and cython_engine.is_available():
                self.logger.info("使用Cython增强比对器进行高性能比对")
                from cython_enhanced_comparer import CythonEnhancedComparer
                
                # 创建进度回调
                def cython_progress_callback(percent, status="", detail=""):
                    # 将内部进度(0~100)映射到界面进度条的剩余10%
                    mapped_pct = base_progress + int(percent / 10)
                    progress.update_progress(mapped_pct, status, detail)
                
                # 使用Cython比对器
                comparer = CythonEnhancedComparer(
                    max_diff_reports=100,
                    use_parallel=True
                )
                
                # 使用新版接口 compare_files_enhanced
                results = comparer.compare_files_enhanced(
                    frames1,
                    frames2,
                    compare_range,
                    cython_progress_callback,
                    frame_format,
                    frame_format
                )
                
                # 将帧列表保存到结果中，便于后续界面根据 frame_count 查找对应索引
                # 这两个字段在 compare_files_enhanced 的返回中缺失，导致后续无法显示正确的帧序号
                results['frames1'] = frames1
                results['frames2'] = frames2

                # 转换结果格式
                return self._convert_cython_results(results)
            else:
                # Cython不可用，使用优化的NumPy比对器
                self.logger.warning("Cython不可用，使用优化的NumPy比对器")
                numpy_comparer = OptimizedNumpyComparer(use_parallel=True)
                
                # 批量比对
                batch_result = numpy_comparer.batch_compare_optimized(
                    frames1, frames2, compare_range
                )
                
                # 构建结果
                results = {}
                
                # 处理批量比对结果
                for mismatch in batch_result['mismatches']:
                    frame_idx = mismatch['frame_index']
                    frame1 = frames1[frame_idx]
                    frame2 = frames2[frame_idx]
                    
                    vc = frame1.get('virtual_channel', 0)
                    if vc not in results:
                        results[vc] = {
                            'total_frames': 0,
                            'matching_frames': 0,
                            'mismatched_frames': 0,
                            'error_frames': 0,
                            'mismatches': []
                        }
                    
                    results[vc]['total_frames'] += 1
                    results[vc]['mismatched_frames'] += 1
                    
                    # 添加差异详情
                    mismatch_info = {
                        'frame1': frame1,
                        'frame2': frame2,
                        'differences': mismatch
                    }
                    results[vc]['mismatches'].append(mismatch_info)
                
                # 统计匹配的帧
                total_frames = len(frames1)
                for i in range(total_frames):
                    if i not in [m['frame_index'] for m in batch_result['mismatches']]:
                        frame = frames1[i]
                        vc = frame.get('virtual_channel', 0)
                        if vc not in results:
                            results[vc] = {
                                'total_frames': 0,
                                'matching_frames': 0,
                                'mismatched_frames': 0,
                                'error_frames': 0,
                                'mismatches': []
                            }
                        results[vc]['total_frames'] += 1
                        results[vc]['matching_frames'] += 1
                
                # 添加错误信息
                for vc_data in results.values():
                    vc_data['error_frames'] = batch_result['error_count']

                # ---- 构造统一格式 ----
                unified_result = {
                    'total_frames': [len(frames1), len(frames2)],
                    'matching_frames': 0,
                    'virtual_channel_results': {}
                }

                for vc_id, vc_data in results.items():
                    matching = vc_data.get('matching_frames', 0)
                    mismatching = vc_data.get('mismatched_frames', 0)

                    frame_comparisons = []
                    for mm in vc_data.get('mismatches', []):
                        f1 = mm.get('frame1', {})
                        fc = int(f1.get('frame_count', -1)) if 'frame_count' in f1 else -1
                        # 确保differences为列表
                        diff_entry = {
                            'field': 'payload',
                            'differences': mm.get('differences', []) if isinstance(mm.get('differences', []), list) else []
                        }
                        frame_comparisons.append({
                            'frame_count': fc,
                            'type': 'content_mismatch',
                            'differences': [diff_entry]
                        })

                    unified_result['virtual_channel_results'][vc_id] = {
                        'vc_id': vc_id,
                        'frames_in_base': vc_data.get('total_frames', 0),
                        'frames_in_target': vc_data.get('total_frames', 0),
                        'matching_frames': matching,
                        'mismatching_frames': mismatching,
                        'missing_in_target': 0,
                        'missing_in_base': 0,
                        'frame_comparisons': frame_comparisons
                    }

                    unified_result['matching_frames'] += matching

                return unified_result

                # 旧结构不再直接返回
                # return results
                
        except Exception as e:
            self.logger.error(f"高性能比对失败，回退到标准方法: {e}")
            # 回退到原始方法
            return self._compare_frames_by_virtual_channel_fallback(
                frames1, frames2, frame_format, compare_range, progress, base_progress
            )
    
    def _compare_frames_by_virtual_channel_fallback(self, frames1, frames2, frame_format, 
                                                   compare_range, progress, base_progress=85):
        """原始的按虚拟信道比对方法（作为备用）"""
        # 使用NumPy优化比对器作为最终备用
        numpy_comparer = OptimizedNumpyComparer(use_parallel=True)

        # 批量比对
        batch_result = numpy_comparer.batch_compare_optimized(
            frames1, frames2, compare_range
        )
        
        # 构建结果
        results = {}
        
        # 处理批量比对结果
        for mismatch in batch_result['mismatches']:
            frame_idx = mismatch['frame_index']
            frame1 = frames1[frame_idx]
            frame2 = frames2[frame_idx]
            
            vc = frame1.get('virtual_channel', 0)
            if vc not in results:
                results[vc] = {
                    'total_frames': 0,
                    'matching_frames': 0,
                    'mismatched_frames': 0,
                    'error_frames': 0,
                    'mismatches': []
                }
            
            results[vc]['total_frames'] += 1
            results[vc]['mismatched_frames'] += 1
            
            # 添加差异详情
            mismatch_info = {
                'frame1': frame1,
                'frame2': frame2,
                'differences': mismatch
            }
            results[vc]['mismatches'].append(mismatch_info)
        
        # 统计匹配的帧
        total_frames = len(frames1)
        for i in range(total_frames):
            if i not in [m['frame_index'] for m in batch_result['mismatches']]:
                frame = frames1[i]
                vc = frame.get('virtual_channel', 0)
                if vc not in results:
                    results[vc] = {
                        'total_frames': 0,
                        'matching_frames': 0,
                        'mismatched_frames': 0,
                        'error_frames': 0,
                        'mismatches': []
                    }
                results[vc]['total_frames'] += 1
                results[vc]['matching_frames'] += 1
        
        # 添加错误信息
        for vc_data in results.values():
            vc_data['error_frames'] = batch_result['error_count']
        
        # 旧结构不再直接返回，继续转换为统一结构
        # return results

        # 添加错误信息
        for vc_data in results.values():
            vc_data['error_frames'] = batch_result['error_count']

        # ---- 构造统一格式（fallback） ----
        unified_result = {
            'total_frames': [len(frames1), len(frames2)],
            'matching_frames': 0,
            'virtual_channel_results': {}
        }
        for vc_id, vc_data in results.items():
            matching = vc_data.get('matching_frames', 0)
            mismatching = vc_data.get('mismatched_frames', 0)
            frame_comparisons = []
            for mm in vc_data.get('mismatches', []):
                f1 = mm.get('frame1', {})
                fc = int(f1.get('frame_count', -1)) if 'frame_count' in f1 else -1
                diff_entry = {
                    'field': 'payload',
                    'differences': mm.get('differences', []) if isinstance(mm.get('differences', []), list) else []
                }
                frame_comparisons.append({
                    'frame_count': fc,
                    'type': 'content_mismatch',
                    'differences': [diff_entry]
                })
            unified_result['virtual_channel_results'][vc_id] = {
                'vc_id': vc_id,
                'frames_in_base': vc_data.get('total_frames', 0),
                'frames_in_target': vc_data.get('total_frames', 0),
                'matching_frames': matching,
                'mismatching_frames': mismatching,
                'missing_in_target': 0,
                'missing_in_base': 0,
                'frame_comparisons': frame_comparisons
            }
            unified_result['matching_frames'] += matching

        return unified_result
        # return results

    def _display_page(self, page_num):
        """显示指定页的数据"""
        try:
            # 检查页码是否有效
            if page_num < 1 or page_num > self.total_pages:
                return
            
            # 检查是否已缓存该页数据
            if page_num in self.page_cache:
                # 使用缓存的数据
                page_data = self.page_cache[page_num]
                self._fill_table_with_page_data(page_data)
                self.current_page = page_num
                self._update_pagination_controls()
                return
            
            # 计算该页的数据范围
            start_idx = (page_num - 1) * self.page_size
            end_idx = min(start_idx + self.page_size, len(self.all_rows_data))
            page_rows = self.all_rows_data[start_idx:end_idx]
            
            # 如果需要处理大量数据，显示进度对话框
            if len(page_rows) > 50:
                progress = ProgressDialog(self)
                progress.setWindowTitle("正在加载数据")
                progress.show()
                
                try:
                    self._process_page_data(page_rows, page_num, progress)
                finally:
                    progress.close()
            else:
                # 直接处理数据
                self._process_page_data(page_rows, page_num, None)
            
            self.current_page = page_num
            self._update_pagination_controls()
            
        except Exception as e:
            self.logger.error(f"显示第 {page_num} 页数据失败: {str(e)}")
            QMessageBox.critical(self, "错误", f"显示页面数据失败: {str(e)}")
    
    def _process_page_data(self, page_rows, page_num, progress=None):
        """处理页面数据并显示"""
        try:
            # 预先创建字典以加速帧数据查找
            frames1_dict = {}
            frames2_dict = {}
            if 'frames1' in self.current_comparison:
                frames1_dict = {int(frame['frame_count']): (frame, idx)
                               for idx, frame in enumerate(self.current_comparison.get('frames1', []))}
            if 'frames2' in self.current_comparison:
                frames2_dict = {int(frame['frame_count']): (frame, idx)
                               for idx, frame in enumerate(self.current_comparison.get('frames2', []))}
            
            # 准备页面数据
            page_data = []
            total_rows = len(page_rows)
            
            for idx, row_data in enumerate(page_rows):
                if progress and idx % 10 == 0:
                    percent = int((idx / total_rows) * 100)
                    progress.update_progress(percent, f"正在处理第 {idx + 1}/{total_rows} 条数据", "")
                    QApplication.processEvents()
                
                vc_id = row_data['vc_id']
                frame_result = row_data['frame_result']
                frame_count = row_data['frame_count']
                
                # 获取基准/目标帧索引和虚拟信道帧计数
                base_entry = frames1_dict.get(frame_count)
                target_entry = frames2_dict.get(frame_count)
                base_frame, base_idx = base_entry if base_entry else (None, -1)
                target_frame, target_idx = target_entry if target_entry else (None, -1)

                vc_frame_count = frame_count  # 默认使用普通帧计数

                # 优先从基准帧提取虚拟信道帧计数
                frame_for_vc = base_frame if base_frame else target_frame
                if frame_for_vc:
                    try:
                        from frame_processor import FrameProcessor
                        vc_frame_count = FrameProcessor.extract_virtual_channel_frame_count(frame_for_vc) or frame_count
                    except Exception:
                        pass

                # 准备行数据
                row_info = {
                    'vc_id': vc_id,
                    'vc_frame_count': vc_frame_count,
                    'frame_result': frame_result,
                    'frame_count': frame_result['frame_count'],
                    'base_idx': base_idx,
                    'target_idx': target_idx
                }
                page_data.append(row_info)
            
            # 缓存页面数据
            self.page_cache[page_num] = page_data
            
            # 填充表格
            self._fill_table_with_page_data(page_data)
            
            if progress:
                progress.update_progress(100, "完成", "")
                
        except Exception as e:
            self.logger.error(f"处理页面数据失败: {str(e)}")
            raise
    
    def _fill_table_with_page_data(self, page_data):
        """使用页面数据填充表格"""
        try:
            # 设置表格行数
            self.diff_table.setRowCount(len(page_data))
            
            # 禁用表格更新以提高性能
            self.diff_table.setUpdatesEnabled(False)
            
            try:
                for row_idx, row_info in enumerate(page_data):
                    vc_id = row_info['vc_id']
                    vc_frame_count = row_info['vc_frame_count']
                    frame_result = row_info['frame_result']
                    
                    # 虚拟信道列
                    vc_item = QTableWidgetItem(f"VC{vc_id}")
                    vc_item.setTextAlignment(Qt.AlignCenter)
                    self.diff_table.setItem(row_idx, 0, vc_item)
                    
                    # 帧计数列 - 格式化为十六进制
                    hex_str = format(vc_frame_count, '06X')
                    formatted_hex = ' '.join(hex_str[i:i+2] for i in range(0, len(hex_str), 2))
                    count_item = QTableWidgetItem(formatted_hex)
                    count_item.setTextAlignment(Qt.AlignCenter)
                    self.diff_table.setItem(row_idx, 1, count_item)
                    
                    # 比对结果列
                    if frame_result['type'] == 'content_mismatch':
                        result_item = QTableWidgetItem("不同")
                        result_item.setBackground(Qt.red)
                        result_item.setForeground(Qt.white)
                        
                        # 构建差异详情
                        diff_objects = frame_result.get('differences', [])
                        diff_count = 0
                        if diff_objects:
                            first_obj = diff_objects[0]
                            if isinstance(first_obj, dict):
                                # 新格式，包含字段信息
                                for diff in diff_objects:
                                    if diff.get('field', 'payload') == 'payload':
                                        diff_count = len(diff.get('differences', []))
                                        break
                            else:
                                # 旧格式，直接为字节差异列表
                                diff_count = len(diff_objects)
                        
                        diff_detail = f"数据区有{diff_count}处差异" if diff_count > 0 else "有差异"
                        
                    elif frame_result['type'] == 'missing_in_target':
                        result_item = QTableWidgetItem("目标文件缺失")
                        result_item.setBackground(Qt.yellow)
                        result_item.setForeground(Qt.black)
                        diff_detail = "此帧在目标文件中不存在"
                    elif frame_result['type'] == 'missing_in_base':
                        result_item = QTableWidgetItem("基准文件缺失")
                        result_item.setBackground(Qt.cyan)
                        result_item.setForeground(Qt.black)
                        diff_detail = "此帧在基准文件中不存在"
                    else:
                        result_item = QTableWidgetItem("未知")
                        diff_detail = ""
                    
                    result_item.setTextAlignment(Qt.AlignCenter)
                    self.diff_table.setItem(row_idx, 2, result_item)
                    
                    # 构建帧索引说明
                    base_idx = row_info.get('base_idx', -1)
                    target_idx = row_info.get('target_idx', -1)
                    
                    base_idx_str = f"#{base_idx + 1}" if base_idx != -1 else "缺失"
                    target_idx_str = f"#{target_idx + 1}" if target_idx != -1 else "缺失"
                    
                    index_info = f"基准帧 {base_idx_str} / 目标帧 {target_idx_str}"
                    full_detail = f"{index_info} | {diff_detail}" if diff_detail else index_info

                    # 差异详情列
                    diff_item = QTableWidgetItem(full_detail)
                    self.diff_table.setItem(row_idx, 3, diff_item)
                
            finally:
                # 重新启用表格更新
                self.diff_table.setUpdatesEnabled(True)
            
            # 调整表格列宽
            self.diff_table.resizeColumnsToContents()
            # 让最后一列（差异详情）占据剩余空间
            header = self.diff_table.horizontalHeader()
            header.setStretchLastSection(True)
            
        except Exception as e:
            self.logger.error(f"填充表格数据失败: {str(e)}")
            raise
    
    def _update_pagination_controls(self):
        """更新分页控件状态"""
        # 更新页码显示
        self.page_info_label.setText(f"第 {self.current_page} 页 / 共 {self.total_pages} 页")
        
        # 更新按钮状态
        self.prev_page_btn.setEnabled(self.current_page > 1)
        self.next_page_btn.setEnabled(self.current_page < self.total_pages)
    
    def _go_to_prev_page(self):
        """跳转到上一页"""
        if self.current_page > 1:
            self._display_page(self.current_page - 1)
    
    def _go_to_next_page(self):
        """跳转到下一页"""
        if self.current_page < self.total_pages:
            self._display_page(self.current_page + 1)

    def _convert_cython_results(self, results):
        """将Cython增强比对器返回的结果转换为现有界面可识别的统一格式。
        目前 compare_files_enhanced 已经返回了符合统一格式（包含
        total_frames、matching_frames、virtual_channel_results 等字段），
        因此这里直接返回即可。如果未来格式发生变化，可在此进行适配。"""
        return results
